﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace XapSpyAnalysis
{
    class Statistic
    {
        public int NumberCalls { get; set; }
        public int NumberUniqueMethods { get; set; }
        public List<string> ListOfUniqueMethodStrings { get; set; }
        public List<Data> ListOfUniqueData { get; set; }
        public List<CountCallEntry> CountCallsList { get; set; }
        public Dictionary<string, int> CountCallsDictionary { get; set; }

        // needs to be set on a time basis for the Statistic object
        public List<Data> DataList { get; set; }

        /// <summary>
        /// Filters a given input list for duplicates and returns only methods that
        /// were called once.
        /// </summary>
        /// <param name="DataList">A List of Data objects.</param>
        /// <returns>A List of Data objects with single occurences of methods.</returns>
        public List<Data> filterDuplicates()
        {
            Dictionary<Data, string> uniqueStore = new Dictionary<Data, string>();
            List<Data> finalList = new List<Data>();

            foreach (Data currValue in DataList)
            {
                if (!uniqueStore.ContainsValue(currValue.MethodName))
                {
                    uniqueStore.Add(currValue, currValue.MethodName);
                    finalList.Add(currValue);
                }
            }
            return finalList;
        }

        /// <summary>
        /// Creates a Dictionary with method names and their counted calls.
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, int> countCalls()
        {
            Dictionary<string, int> result = new Dictionary<string, int>();
            // initialize counter
            int count = 0;
            foreach (Data item in DataList)
            {
                // for each Data item, we need to initialize with 0, because 
                // its unknown if it already exists in the dictionary
                count = 0;
                // check if the method name is on the ListOfUniqueMethodStrings
                if (ListOfUniqueMethodStrings.Contains(item.MethodName))
                {
                    // check if there is in dictionary already a corresponding entry
                    if (result.ContainsKey(item.MethodName))
                    {
                        // get the current count number
                        result.TryGetValue(item.MethodName, out count);
                        // count one call up
                        count++;
                        // refresh the dictionary entry with new count
                        result[item.MethodName] = count;
                    }
                    else
                    {
                        // it is the first time, that we add a method to the dictionary
                        result.Add(item.MethodName, 1);
                    }
                }
            }
            CountCallsDictionary = result;
            return result;
        }

        /// <summary>
        /// Creates a List of strings with unique method names. 
        /// </summary>
        /// <param name="inputList">The input List in where the unique methods are saved.</param>
        /// <returns>A List of strings with unique method names.</returns>
        public List<string> listOfUniqueMethodNames(List<Data> inputList)
        {
            List<string> result = new List<string>();
            foreach (Data item in inputList)
            {
                result.Add(item.MethodName);
            }
            return result;
        }

        /// <summary>
        /// Calculates for a given Statistic object its statistic values and assigns
        /// them to the statistic object.
        /// </summary>
        /// <param name="statistic">The Statistic object for which the calculation will be executed.</param>
        public void calculateStatistic()
        {
            // calculates numbers for the statistics
            NumberCalls = this.NumberCalls;
            // relies on a List<Data> before calculation
            NumberUniqueMethods = this.filterDuplicates().Count;
            ListOfUniqueData = filterDuplicates();
            ListOfUniqueMethodStrings = listOfUniqueMethodNames(ListOfUniqueData);
        }

        /// <summary>
        /// Converts the CountDictionary to CountCallsList.
        /// </summary>
        /// <param name="dictionary"></param>
        /// <returns></returns>
        public List<CountCallEntry> convertCountDictionaryToList(Dictionary<string, int> dictionary)
        {
            List<CountCallEntry> result = new List<CountCallEntry>();
            foreach (var item in dictionary)
            {
                CountCallEntry cce = new CountCallEntry();
                cce.MethodName = item.Key;
                cce.Count = item.Value;
                result.Add(cce);
            }
            CountCallsList = result;
            return result;
        }
    }
}
